#include <iostream>
#include <vector>
#include <queue>
#include <string>
#include <pthread.h>

 // 单例模式线程池

struct ThreadInfo
{
    pthread_t tid;
    std::string name;
};

static const int defaultNum = 5;

template <class T>
class ThreadPool
{
public:
    void Lock()
    {
        pthread_mutex_lock(&_mutex);
    }
    void Unlock()
    {
        pthread_mutex_unlock(&_mutex);
    }
    void ThreadWait()
    {
        pthread_cond_wait(&_cond, &_mutex);
    }
    bool IsEmpty()
    {
        return _tasks.empty();
    }
public:
    static void *HandlerTask(void *args)
    {
        ThreadPool<T> *tp = static_cast<ThreadPool<T>*>(args);
        std::string name = tp->GetThreadNams(pthread_self());
        std::cout << name << std::endl;
        while (true)
        {
            // pthread_mutex_lock(&_mutex);
            tp->Lock();
            // while (tp->_tasks.empty())
            while (tp->IsEmpty())
            {
                // pthread_cond_wait(&_cond, &_mutex);
                tp->ThreadWait();
            }
            T t = tp->Pop();
            // pthread_mutex_unlock(&_mutex);
            tp->Unlock();
            t();
        }
        return nullptr;
    }
    void Start()
    {
        int num = _threads.size();
        for (int i = 0; i < num; i++)
        {
            _threads[i].name = "thread-" + std::to_string(i);
            pthread_create(&(_threads[i].tid), nullptr, HandlerTask, this);
        }
    }
    void Push(const T &t)
    {
        pthread_mutex_lock(&_mutex);
        _tasks.push(t);
        pthread_cond_signal(&_cond);
        pthread_mutex_unlock(&_mutex);
    }
    T Pop()
    {
        T task = _tasks.front();
        _tasks.pop();
        return task;
    }
    std::string GetThreadNams(pthread_t tid)
    {
        for (const auto &ti : _threads)
        {
            if (ti.tid == tid) return ti.name; 
        }
        return "None";
    }
    static ThreadPool<T> *GetInstance()
    {
        if (tp_ == nullptr)  // 两层先检测,解决在tp_ != nullptr的情况下,多线程访问判断tp_时只能一个一个来,提高效率
        {
            pthread_mutex_lock(&lock_);
            if (tp_ == nullptr)
            {
                std::cout << "log: singleton create done first!" << std::endl;
                tp_ = new ThreadPool<T>();
            }
            pthread_mutex_unlock(&lock_);
        }
        return tp_;
    }
private:
    // 构造
    ThreadPool(int num = defaultNum) :_threads(defaultNum)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);
    }
    // 析构
    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
    }
    ThreadPool(const ThreadPool<T> &) = delete;
    const ThreadPool<T> &operator=(const ThreadPool<T> &) = delete;
private:
    std::vector<ThreadInfo> _threads;
    std::queue<T> _tasks;
    pthread_mutex_t _mutex;
    pthread_cond_t _cond;

    static ThreadPool<T> *tp_;
    static pthread_mutex_t lock_;  // 防止多线程访问GetInstance()
};

template<class T>
ThreadPool<T> *ThreadPool<T>::tp_ = nullptr;
template<class T>
pthread_mutex_t ThreadPool<T>::lock_ = PTHREAD_MUTEX_INITIALIZER;